#pragma once
#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "Log.hpp"
#include "Socket.hpp"

static const uint16_t defaultport = 8888;
static const int fd_num_max = 64;
int defaultfd = -1;
int non_event = 0;

class PollServer
{
public:
    PollServer(uint16_t port = defaultport)
        : port_(port)
    {
        for(int i=0;i<fd_num_max;i++)
        {
           _event_fds[i].fd=defaultfd;
           _event_fds[i].events=non_event;
           _event_fds[i].revents=non_event;
        }
    }
    ~PollServer()
    {
        listensocket_.Close();
    }
    
    void Init()
    {
        listensocket_.Socket();
        listensocket_.Bind(port_);
        listensocket_.Listen();

    }
    void Accepter()
    {
        std::string clientip;
        uint16_t clientport = 0;
        int sockfd = listensocket_.Accept(&clientip, &clientport);
        if (sockfd < 0)
        {
            return;
        }
        lg(Info, "accept success, %s: %d, sock fd: %d", clientip.c_str(), clientport, sockfd);

        int pos = 1;
        for (; pos < fd_num_max; pos++)
        {
            if (_event_fds[pos].fd != defaultfd)
                continue;
            else
                break;
        }
        if (pos == fd_num_max)
        {
            lg(Warning, "server is full, close %d now!", sockfd);
            close(sockfd);
        }
        else
        {
            _event_fds[pos].fd = sockfd;
            _event_fds[pos].events=POLLIN;
            _event_fds[pos].revents= non_event;
            PrintFd();
            // TODO
        }
    }
    void Recver(int fd,int pos)
    {
        char buffer[1024];
        ssize_t n=read(fd,buffer,sizeof(buffer)-1);//有bug，这里不能保证是读完整的
        if(n>0)
        {
            buffer[n] = 0;
            std::cout << "get a messge: " << buffer << std::endl;
        }
        else if(n==0)
        {
            lg(Info, "client quit, me too, close fd is : %d", fd);
            close(fd);
            _event_fds[pos].fd = defaultfd; // 这里本质是从select中移除
        }
        else
        {
            lg(Warning, "recv error: fd is : %d", fd);
            close(fd);
           _event_fds[pos].fd = defaultfd; // 这里本质是从select中移除
        }
    }
    void Dispatcher()
    {
        for(int i=0;i<fd_num_max;i++)
        {
            int fd=_event_fds[i].fd;
            if(fd==defaultfd) continue;
            if(_event_fds[i].revents&POLLIN)
            {
//使用 revents 而不是 events：
//在调用 poll 之后，revents 成员会被填充以指示哪些事件在指定的文件描述符上实际发生了。events 成员是你传递给 poll 的，用于指定你想要监视的事件类型。由于你想要检查实际发生的事件，因此应该使用 revents。
//使用 POLLIN 而不是 POLLOUT：
//在这个 Dispatcher 函数中，你正在检查哪些文件描述符有可读的事件（即 POLLIN）。这意味着你正在查看哪些套接字有数据可读（可能是新的连接请求，或者是已经连接的客户端发送的数据）。
//POLLOUT 表示可写事件，即套接字准备好发送数据。在这个上下文中，你并不关心哪些套接字准备好发送数据，因为你是服务器，你更关心是否有新的连接请求或已连接客户端发送的数据。
                if (fd == listensocket_.Fd())
                {
                    Accepter(); // 连接管理器
                }
                else // non listenfd
                {
                    Recver(fd, i);
                }
            }
        }
    }
    void PrintFd()
    {
        std::cout << "online fd list: ";
        for (int i = 0; i < fd_num_max; i++)
        {
            if (_event_fds[i].fd == defaultfd)
                continue;
            std::cout << _event_fds[i].fd << " ";
        }
        std::cout << std::endl;
    }
    void Start()
    {
        int listen_fd = listensocket_.Fd();
        _event_fds[0].fd= listen_fd;
        _event_fds[0].events=POLLIN;
        //events 成员用于告诉 poll 系统调用你想要监视哪些事件。在这个例子中，你只关心是否有新的连接请求到达（即数据可读)
       // POLLIN 表示你关心的是文件描述符上的数据可读事件。在服务器接受新连接的上下文中，这通常意味着有新的客户端连接请求到达。
        //POLLOUT 表示你关心的是文件描述符上的数据可写事件。在服务器上下文中，这通常用于检查是否可以向某个已连接的客户端发送数据。但是，在 accept 调用之前（即在你还没有接受新的连接之前），
        //POLLOUT 对于监听套接字（listen socket）是没有意义的，因为你还没有与任何客户端建立连接来发送数据。
        int timeout = 3000; // 3s
        for (;;)
        {
            int n=poll(_event_fds,fd_num_max,timeout);
            switch (n)
            {
            case 0:
                std::cout << "time out... " << std::endl;
                break;
            case -1:
                std::cerr << "poll error" << std::endl;
                break;
            default:
                // 有事件就绪了，TODO
                std::cout << "get a new link!!!!!" << std::endl;
                Dispatcher(); // 就绪的事件和fd你怎么知道只有一个呢？？？
                break;
            }
        }
    }

private:
    uint16_t port_;
    Sock listensocket_;
    struct pollfd _event_fds[fd_num_max]; // 数组, 用户维护的！
};